package textchorus.sparql;

import java.net.*;
import java.util.*;
import java.io.*;
import textchorus.*;

public class SparqlQuery {
	PSketch pSketch;
	XMLParse xmlParse;
	String query;
	URL queryURL;
	HttpURLConnection urlConn;

	private static final String _defaultParam = "default-graph-uri=http://dbpedia.org&format=application/sparql-results+xml&debug=on";
//	private static final String _sparqlEndPt = "http://dbpedia.org/sparql";
	private static final String _sparqlEndPt = "http://localhost:8890/sparql";	
	
	public enum Tag {
		S, P, O
	};

	public SparqlQuery(Map<SparqlQuery.Tag, String> q) {
		query = "SELECT * WHERE {";
		boolean sFlag = false;
		boolean pFlag = false;
		boolean oFlag = false;
		String sStr = null;
		String pStr = null;
		String oStr = null;
		
		Iterator<?> iter = q.entrySet().iterator();
		while(iter.hasNext()) { 
		    Map.Entry<?,?> entry = (Map.Entry<?,?>)iter.next();
		    Tag key = (Tag)entry.getKey();
		    String value = (String)entry.getValue();
		    
			switch (key) {
			case S:
				sFlag = true;
				sStr = value;
				break;
			case P:
				pFlag = true;
				pStr = value;
				break;
			case O:
				oFlag = true;
				oStr = value;
				break;
			default:
				break;
			}
		}
		
		if(sFlag) {
			query = query.concat("<"+ sStr + "> ");
		} else {
			query = query.concat("?s ");
		}
		if(pFlag) {
			query = query.concat("<" + pStr + "> ");
		} else {
			query = query.concat("?p ");
		}
		if(oFlag) {
			query = query.concat("<" + oStr + ">");
		} else {
			query = query.concat("?o");
		}
		
		query = query.concat("}");
		System.out.println(">>> SPARQL query generated: " + query);
		query = encodeString(query);
		
		String msg = _defaultParam + "&query=" + query;
		
//		System.out.println("POST query:" + msg);
		
		byte[] msgAsBytes = msg.getBytes();

		try {
			queryURL = new URL(_sparqlEndPt);
			urlConn = (HttpURLConnection) queryURL.openConnection();
			urlConn.setRequestMethod("POST");

			urlConn.setDoOutput(true);
			urlConn.setDoInput(true);
			urlConn.setConnectTimeout(0);
			urlConn.setReadTimeout(0);
			urlConn.setUseCaches(false);

			OutputStream oStream = urlConn.getOutputStream();
			oStream.write(msgAsBytes);
			oStream.flush();

			BufferedReader iStream = new BufferedReader(new InputStreamReader(
					urlConn.getInputStream()));

			String aLine = "";
			String xmlResult = "";
			
			while ((aLine = iStream.readLine()) != null) {
				xmlResult = xmlResult.concat(aLine + "\n");
//				System.out.println(aLine);
			}
			
			xmlParse = new XMLParse(xmlResult);
						
			oStream.close();
			iStream.close();

		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			try {
				InputStream es = urlConn.getErrorStream();
				int ret = 0;
				while ((ret = es.read()) > 0) {
					System.out.print((char) ret);
				}
				System.out.println();
				es.close();
			} catch (IOException ex) {
				// deal with the exception
			}

			e.printStackTrace();
		}
	}

	public String getLabel() throws NullPointerException {
		if(xmlParse==null)
			throw new NullPointerException();
		
		System.out.println("LABEL:");
		HashMap<Tag, String> search = new HashMap<Tag, String>();
		search.put(Tag.P,"http://www.w3.org/2000/01/rdf-schema#label");
		
		// there should only be one abstract, so return the first element from the result vector
		String res = xmlParse.searchElement(search,Tag.O).get(0);
		System.out.println(res);
		
		return res;
	}
	
	public String getAbstract() throws NullPointerException {
		if(xmlParse==null)
			throw new NullPointerException();
		
		System.out.println("ABSTRACT:");
		HashMap<Tag, String> search = new HashMap<Tag, String>();
		search.put(Tag.P,"http://dbpedia.org/property/abstract");
		
		// there should only be one abstract, so return the first element from the result vector
		String res = xmlParse.searchElement(search,Tag.O).get(0);
		System.out.println(res);
		
		return res;
	}
	
	public Vector<String> getDisambiguations() throws NullPointerException {
		if(xmlParse==null)
			throw new NullPointerException();
		
//		System.out.println("DISAMBIGUATIONS:");
		HashMap<Tag, String> search = new HashMap<Tag, String>();
		search = new HashMap<Tag, String>();
		search.put(Tag.P,"http://dbpedia.org/property/disambiguates");
					
		Vector<String> res = xmlParse.searchElement(search, Tag.O);
		System.out.println(res);
		System.out.println();

		return res;		
	}
	
	public Vector<String> getSubjects() throws NullPointerException {
		if(xmlParse==null)
			throw new NullPointerException();
		
//		System.out.println("SUBJECTS:");
		HashMap<Tag, String> search = new HashMap<Tag, String>();
		search = new HashMap<Tag, String>();
		search.put(Tag.P,"http://www.w3.org/2004/02/skos/core#subject");
					
		Vector<String> res = xmlParse.searchElement(search, Tag.O);
//		System.out.println(res);
//		System.out.println();
		
		return res;
		
	}
	
	public Vector<String> getArticles() throws NullPointerException {
		if(xmlParse==null)
			throw new NullPointerException();

		System.out.println("ARTICLES:");
		HashMap<Tag, String> search = new HashMap<Tag, String>();
		search = new HashMap<Tag, String>();
		search.put(Tag.S,"*");

		Vector<String> res = xmlParse.searchElement(search, Tag.S);
		System.out.println(res);
		System.out.println();
		
		return res;
	}
	
	
	private String encodeString(String str) {
		String encoded = null;
		try {
			encoded = URLEncoder.encode(str, "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		return encoded;
	}

}

